import os
import tkinter as tk
from tkinter import Frame, Label, Button, filedialog, messagebox, StringVar, Entry, Tk
from tkinter.ttk import Progressbar, Separator, Style
import socket
import threading
import webbrowser
from http.server import ThreadingHTTPServer, SimpleHTTPRequestHandler


class SharedFileHandler(SimpleHTTPRequestHandler):
    """自定义HTTP请求处理类，用于处理文件共享"""

    def __init__(self, *args, **kwargs):
        # 设置共享目录
        directory = os.path.join(os.getcwd(), 'shared_files')
        super().__init__(*args, directory=directory, **kwargs)

    def log_message(self, format, *args):
        # 禁用默认的日志输出
        pass

    def end_headers(self):
        # 添加CORS头，允许跨域访问
        self.send_header('Access-Control-Allow-Origin', '*')
        super().end_headers()


class FileSharingApp:
    def __init__(self, root):
        self.root = root
        self.root.title("内网文件共享工具 v1.0")
        self.root.geometry("400x380")
        self.root.resizable(False, False)
        self.root.configure(bg='#f0f0f0')  # 设置窗口背景色

        # 样式设置 - 仅用于ttk小部件
        self.style = Style()
        self.style.configure('TLabel', font=('微软雅黑', 10))
        self.style.configure('TButton', font=('微软雅黑', 10), padding=5)
        self.style.configure('Title.TLabel', font=('微软雅黑', 14, 'bold'))

        # 主框架 - 使用标准Frame
        self.main_frame = Frame(root, bg='#f0f0f0')
        self.main_frame.pack(fill='both', expand=True, padx=10, pady=10)

        # 标题区域
        self.title_frame = Frame(self.main_frame, bg='#f0f0f0')
        self.title_frame.pack(fill='x', pady=(0, 10))

        title_label = Label(self.title_frame, text="内网文件共享工具", bg='#f0f0f0',
                            font=('微软雅黑', 14, 'bold'))
        title_label.pack(anchor='w')

        # 分隔线 - 使用ttk Separator
        Separator(self.main_frame, orient='horizontal').pack(fill='x', pady=5)

        # 配置区域
        self.config_frame = Frame(self.main_frame, bg='#f0f0f0')
        self.config_frame.pack(fill='x', pady=10)

        self.port_var = StringVar(value="8000")
        Label(self.config_frame, text="共享端口:", bg='#f0f0f0',
              font=('微软雅黑', 10)).grid(row=0, column=0, sticky='e', padx=5)
        self.port_entry = Entry(self.config_frame, textvariable=self.port_var, width=10)
        self.port_entry.grid(row=0, column=1, sticky='w')

        # 按钮区域
        self.button_frame = Frame(self.main_frame, bg='#f0f0f0')
        self.button_frame.pack(fill='x', pady=10)

        Button(self.button_frame, text="选择共享文件", command=self.select_files,
               width=15, font=('微软雅黑', 10)).pack(side='left', padx=5)
        Button(self.button_frame, text="打开共享目录", command=self.open_shared_dir,
               width=15, font=('微软雅黑', 10)).pack(side='left', padx=5)
        Button(self.button_frame, text="清空共享目录", command=self.clear_shared_dir,
               width=15, font=('微软雅黑', 10)).pack(side='left', padx=5)

        # 控制区域
        self.control_frame = Frame(self.main_frame, bg='#f0f0f0')
        self.control_frame.pack(fill='x', pady=10)

        self.start_btn = Button(self.control_frame, text="启动共享", command=self.start_sharing,
                                width=15, bg='#4CAF50', fg='white', font=('微软雅黑', 10))
        self.start_btn.pack(side='left', padx=5)

        self.stop_btn = Button(self.control_frame, text="停止共享", command=self.stop_sharing,
                               width=15, bg='#F44336', fg='white', font=('微软雅黑', 10), state='disabled')
        self.stop_btn.pack(side='left', padx=5)

        # 状态区域
        self.status_frame = Frame(self.main_frame, bg='#f0f0f0')
        self.status_frame.pack(fill='x', pady=10)

        self.status_label = Label(self.status_frame, text="状态: 未启动", fg="gray", bg='#f0f0f0',
                                  font=('微软雅黑', 10))
        self.status_label.pack()

        # 修改为可点击的标签
        self.access_label = Label(self.status_frame, text="访问地址: 未设置地址", fg="blue", bg='#f0f0f0',
                                  font=('微软雅黑', 10), cursor="hand2")
        self.access_label.pack()
        self.access_label.bind("<Button-1>", self.copy_access_url)

        # 底部信息
        Separator(self.main_frame, orient='horizontal').pack(fill='x')

        Label(self.main_frame, text="© 2025 内网文件共享工具 | 版本 1.0",
              bg='#f0f0f0', font=('微软雅黑', 10)).pack(side='bottom', pady=5)

        # 初始化变量
        self.server = None
        self.server_thread = None
        self.shared_dir = os.path.join(os.getcwd(), 'shared_files')
        os.makedirs(self.shared_dir, exist_ok=True)

    def clear_shared_dir(self):
        """清空共享目录"""
        try:
            # 停止服务以避免冲突
            if self.server:
                self.stop_sharing()

            # 删除共享目录中的所有文件
            for filename in os.listdir(self.shared_dir):
                file_path = os.path.join(self.shared_dir, filename)
                if os.path.isfile(file_path):
                    os.remove(file_path)
                elif os.path.isdir(file_path):
                    import shutil
                    shutil.rmtree(file_path)

            messagebox.showinfo("成功", "共享目录已清空")
        except Exception as e:
            messagebox.showerror("错误", f"清空共享目录失败: {e}")

    def select_files(self):
        """选择要共享的文件"""
        filenames = filedialog.askopenfilenames(title="选择要共享的文件")
        if filenames:
            os.makedirs(self.shared_dir, exist_ok=True)
            self.upload_progress["maximum"] = len(filenames)

            for i, filename in enumerate(filenames, 1):
                try:
                    dest = os.path.join(self.shared_dir, os.path.basename(filename))
                    # 确保目标目录存在
                    os.makedirs(os.path.dirname(dest), exist_ok=True)
                    # 使用shutil.copy2保持文件元数据
                    import shutil
                    shutil.copy2(filename, dest)
                    self.upload_progress["value"] = i
                    self.root.update()
                except Exception as e:
                    messagebox.showerror("错误", f"复制文件失败: {e}")

            self.upload_progress["value"] = 0
            messagebox.showinfo("成功", f"已添加 {len(filenames)} 个文件到共享目录")

    def open_shared_dir(self):
        """打开共享目录"""
        try:
            os.startfile(self.shared_dir)
        except Exception as e:
            messagebox.showerror("错误", f"无法打开共享目录: {e}")

    def is_port_available(self, port):
        """检查端口是否可用"""
        import socket
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            return s.connect_ex(('localhost', port)) != 0

    def start_sharing(self):
        """启动文件共享服务"""
        if self.server is not None:
            messagebox.showwarning("警告", "共享服务已经在运行中")
            return

        try:
            port = int(self.port_var.get())
        except ValueError:
            messagebox.showerror("错误", "请输入有效的端口号")
            return

        if not self.is_port_available(port):
            messagebox.showerror("错误", f"端口 {port} 已被占用，请使用其他端口")
            return

        try:
            # 创建并启动HTTP服务器
            self.server = ThreadingHTTPServer(('0.0.0.0', port), SharedFileHandler)
            self.server.app = self  # 将应用实例传递给服务器
            self.server_thread = threading.Thread(target=self.server.serve_forever)
            self.server_thread.daemon = True
            self.server_thread.start()

            self.status_label.config(text=f"状态: 共享中 (端口: {port})", fg="green")

            # 获取本机IP地址
            local_ip = self.get_local_ip()
            access_url = f"http://{local_ip}:{port}"
            self.access_label.config(text=f"访问地址: {access_url}")

            self.start_btn.config(state='disabled')
            self.stop_btn.config(state='normal')

            # 自动打开浏览器访问共享服务
            webbrowser.open(access_url)

        except Exception as e:
            error_message = str(e)
            messagebox.showerror("错误", f"启动共享失败: {error_message}")
            if self.server:
                self.server.shutdown()
                self.server = None

    def stop_sharing(self):
        """停止文件共享服务"""
        if self.server:
            try:
                # 停止服务器
                self.server.shutdown()
                self.server.server_close()
                self.server_thread.join()

                # 更新UI状态
                self.server = None
                self.server_thread = None
                self.status_label.config(text="状态: 已停止", fg="red")
                self.access_label.config(text="访问地址: 未启动")
                self.start_btn.config(state='normal')
                self.stop_btn.config(state='disabled')

            except Exception as e:
                messagebox.showerror("错误", f"停止共享失败: {e}")

    def get_local_ip(self):
        """获取本机真实内网IP"""
        try:
            # 方法1：通过UDP连接获取
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(("8.8.8.8", 80))  # 连接Google DNS服务器
            ip = s.getsockname()[0]
            s.close()
            return ip
        except Exception as e:
            print(f"方法1获取IP失败: {e}")
            try:
                # 方法2：遍历所有网络接口
                hostname = socket.gethostname()
                ip_list = socket.gethostbyname_ex(hostname)[2]
                for ip in ip_list:
                    if not ip.startswith("127."):
                        return ip
                # 如果没有找到合适的IP，返回本地主机名
                return socket.gethostbyname(hostname)
            except Exception as e2:
                print(f"方法2获取IP失败: {e2}")
                # 回退方案：使用传统方法
                return socket.gethostbyname(socket.gethostname())

    def copy_access_url(self, event):
        """复制访问URL到剪贴板"""
        current_text = self.access_label.cget("text")
        if current_text.startswith("访问地址: http://"):
            url = current_text[5:].strip()  # 去掉"访问地址: "前缀
            self.root.clipboard_clear()
            self.root.clipboard_append(url)
            self.root.update()  # 确保剪贴板内容被更新

            # 显示复制成功的提示
            self.show_tooltip("已复制到剪贴板")

    def show_tooltip(self, message):
        """显示临时提示"""
        tooltip = tk.Toplevel(self.root)
        tooltip.overrideredirect(True)  # 无边框窗口
        tooltip.geometry(f"+{self.root.winfo_rootx() + 100}+{self.root.winfo_rooty() + 200}")
        tooltip.lift()
        tooltip.attributes("-alpha", 0.9)  # 半透明

        label = tk.Label(tooltip, text=message, bg="#333", fg="white",
                         font=("微软雅黑", 10), padx=10, pady=5)
        label.pack()

        # 2秒后自动关闭提示
        tooltip.after(2000, tooltip.destroy)
